<template>
  <div id="mine-grid" :style="{ width: `${level * size}px`, height: `${level * size}px` }">
    <mine-row v-for="(row, index) in mines" :key="index" :size="size" :mines="row" @bomb="bomb" @flag="flag"></mine-row>
  </div>
</template>

<script>
import MineRow from './MineRow';

export default {
  name: 'mineGrid',
  components: {
    MineRow
  },
  props: {
    // level: {
    //   type: Number,
    //   validator: function(val) {
    //     const levels = [10, 20, 30, 50];
    //     return levels.includes(val)
    //   }
    // }
    level: Number
  },
  data() {
    return {
      mines: []
    };
  },
  computed: {
    size() {
      return 40;
    }
  },
  mounted() {
    const grid = document.getElementById('mine-grid');
    grid.oncontextmenu = () => false;
    this.mines = this.getMineSet();
  },
  methods: {
    getMineSet() {
      const level = this.level;
      const count = level * level;
      // 生成地雷列表基础信息
      const mineArr = Array(level).fill(false).map((item, y) => {
        return Array(level).fill(false).map((row, x) => ({
          x,
          y,
          mines: 0,
          opened: false,
          flag: false
        }));
      });
      // 随机生成地雷列表
      const realMineCount = this.getRealMineCount(level);
      const realMineArr = Array(realMineCount).fill(false).map(item => -1);
      let stepIndex = 0;
      while (stepIndex < realMineCount) {
        const tmpIndex = parseInt(Math.random() * count);
        if (!realMineArr.includes(tmpIndex)) {
          realMineArr[stepIndex] = tmpIndex;
          stepIndex++;
        }
      }
      // 填充地雷列表，地雷数量为-1表示此位置本身即是地雷
      realMineArr.forEach(indexTag => {
        mineArr[indexTag % level][parseInt(indexTag / level)].mines = -1;
      });
      // 计算非地雷位的周围地雷数量
      mineArr.forEach(row => {
        row.forEach(mine => {
          if (mine.mines === -1) return;
          let count = 0;
          for (let xOffSet = -1; xOffSet < 2; xOffSet++) {
            for (let yOffSet = -1; yOffSet < 2; yOffSet++) {
              // 排除被检查点本身的坐标
              if (xOffSet === 0 && yOffSet === 0) continue;
              const targetX = mine.x + xOffSet;
              const targetY = mine.y + yOffSet;
              // 越界检查
              if (targetX < 0 || targetX >= level) continue;
              if (targetY < 0 || targetY >= level) continue;
              const targetMine = mineArr[targetY][targetX];
              if (targetMine.mines === -1) count++;
            }
          }
          mine.mines = count;
        });
      });
      return mineArr;
    },
    getRealMineCount(level) {
      return parseInt(level * level * 0.1);
    },
    bomb(x, y) {
      const mine = this.mines[y][x];
      if (mine.opened) return;
      switch (mine.mines) {
        case -1:
          mine.opened = true;
          console.log('炸了');
          break;
        case 0:
          this.openMineZero(x, y);
          break;
        default:
          mine.flag = false;
          mine.opened = true;
          break;
      }
    },
    flag(x, y) {
      const mine = this.mines[y][x];
      if (mine.opened) return;
      mine.flag = !mine.flag;
    },
    openMineZero(x, y) {
      const mine = this.mines[y][x];
      mine.opened = true;
      const offSets = [-1, 0, 1];
      offSets.forEach(xOffSet => {
        offSets.forEach(yOffSet => {
          if (xOffSet === 0 && yOffSet === 0) return;
          const targetX = mine.x + xOffSet;
          const targetY = mine.y + yOffSet;
          if (targetX < 0 || targetX >= this.level) return;
          if (targetY < 0 || targetY >= this.level) return;
          const targetMine = this.mines[targetY][targetX];
          if (targetMine.opened) return;
          if (targetMine.mines !== 0) {
            targetMine.opened = true;
            return false;
          } else {
            return this.openMineZero(targetX, targetY);
          }
        });
      });
    }
  }
};
</script>

<style lang="less" scoped>
</style>
